/**
 * @namespace 数字生产者
 */
class NumberProductor {
    /**
     * @param {int} intCnt 整数位数==如“1234”，intCnt为4位
     * @param {number} [decimalCnt=2] 小数点后位数，默认为2（当为0时，是整数）
     * @param {boolean} isNegative 是否为负数
     */
    constructor(intCnt = 5, decimalCnt = 2, isNegative) {
        this.intCnt = intCnt;
        this.decimalCnt = decimalCnt;
        this.isNegative = isNegative;
    }


    create() {
        let numStr = this.isNegative ? '-' : '';
        let counter = this.intCnt;
        if (!counter) {
            numStr = numStr.concat('0')
        }
        
        while (counter) {
            const number = Math.floor(Math.random() * 10)
            numStr = numStr.concat(number)
            counter--;
        }
        if (this.decimalCnt) {
            const decimalStr = Math.random().toFixed(this.decimalCnt)
            numStr=numStr.concat('.', decimalStr.split('.')[1])
        }
        // 可能产生0和-0这种对练习没有帮助的数字，递归重新生成
        if (numStr === '0' || numStr === '-0') {
            this.create()
        }
        return Number(numStr);
    }
}

class BooleanRange {
    constructor(index) {
        this.range = [true, false];
        this.index = (index > this.range.length + 1) ? (this.range.length + 1) : index;
    }
    create() {
        return this.range[Math.floor(Math.random() * this.index)]
    }
}

class NumberRange {
    constructor(index) {
        this.range = [2, 3, 4, 5, 6]
        this.index = (index > this.range.length + 1) ? (this.range.length + 1) : index;
    }
    create() {
        return this.range[Math.floor(Math.random() * this.index)]
    }
}

class ExamProductor {

    constructor(topicCnt = 5) {
        this.topicCnt = topicCnt;
        this.topicList = [];
    }
    create() {
        while (this.topicCnt) {
            const current = new NumberProductor(new NumberRange(5).create(), new NumberRange(2).create(), false).create();
            const rate = new NumberProductor(0, new NumberRange(3).create(), new BooleanRange(2).create()).create();

            const topic = [current, rate];
            this.topicList.push({ topic })
            this.topicCnt--;
        }
    }
    calc() {
        this.topicList = this.topicList.map(item => {
            const { topic } = item;
            const [current, rate] = topic;
            const base = (Number(current) / (Number(rate) + 1)).toFixed(2);
            const delta = (base * Number(rate)).toFixed(2)
            return {
                ...item,
                result: [base, delta]
            }
        })
    }
    format(list, tblTitle) {
        const formatedList = list.reduce((pre, curr) => {
            const { topic, result } = curr;
            const [current, rate] = topic;
            const [base, delta] = result || [];
            const formatedRate = String((Number(rate)*100).toFixed(2)).concat('%')
            pre.push({current, rate: formatedRate, base, delta})
            return pre;
        }, [])
        console.table(formatedList, tblTitle)
    }
    output() {
        this.format(this.topicList, ['current', 'rate'])
        setTimeout(() => {
            this.calc()
            this.format(this.topicList, ['current', 'rate', 'base', 'delta'])
        }, 10000)
    }
}

(() => {
    const exam = new ExamProductor()
    exam.create();
    exam.output()
})()